/* 
 * Coded by David Bruno Cortarello <Nomius>. Redistribute under the terms of
 * the BSD-lite license. Bugs, suggests, nor projects: dcortarello@gmail.com.
 *
 * Program: Limshsql
 * Version: 2.0
 *
 *
 * Copyright (c) 2005-2011, David B. Cortarello
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   * Redistributions of source code must retain the above copyright notice
 *     and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above copyright notice
 *     and the following disclaimer in the documentation and/or other materials
 *     provided with the distribution.
 *   * Neither the name of Kwort nor the names of its contributors may be used
 *     to endorse or promote products derived from this software without
 *     specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <time.h>
#include <pwd.h>
#include <sys/types.h>
#include "limshsql.h"
#include "interface.h"
#include "strings.h"
#include "symloader.h"
#include "config.h"

Menus *MenuItems = NULL;
int items = 0;


int ParseCommandsFile(const char *cfg)
{
	FILE *conf_file = NULL;
	char line[4096];
	char **item = NULL;

	if ((conf_file = fopen(cfg, "r")) == NULL) {
		perror(cfg);
		return 1;
	}

	printf("Loading user configuration");

	while (fgets(line, sizeof(line), conf_file) != NULL) {
		item = dstrtok(line, '#');

		/* Sanity check */
		if (item[0] == NULL || item[1] == NULL)
			goto next_line;

		/* Let's support comments */
		if (item[0][0] == '#')
			goto next_line;

		/* Make space for the new item */
		MenuItems = realloc(MenuItems, sizeof(Menus) * (items+1));
		memset(MenuItems+items, '\0', sizeof(Menus));

		MenuItems[items].opt = items+1;
		MenuItems[items].desc = strdup(item[0]);
		MenuItems[items].command = strdup(item[1]);

		/* Let's make extended help optional and trim the last \n to don't screw up the interface */
		if (item[2] != NULL) {
			MenuItems[items].extended_help = strdup(item[2]);
			if (MenuItems[items].extended_help[strlen(MenuItems[items].extended_help)-1] == '\n')
				MenuItems[items].extended_help[strlen(MenuItems[items].extended_help)-1] = '\0';
			items++;
		}
		else {
			MenuItems[items].command[strlen(MenuItems[items].command)-1] = '\0';
			MenuItems[items++].extended_help = NULL;
		}

		printf(".");

next_line:
		freetok(item);
	}
	printf("  " GREEN "[DONE]\n" RESET);
	fclose(conf_file);
	return 0;
}


void to_end_sigterm(int sig)
{
	/* Register the logout */
	time(&now);
	fn = localtime(&now);

	if (RegisterAction(user->pw_name, fn, "Logged out", NULL))
		PoorExitWithDB(1);

	/* Shut the whole thing down */
	CloseDB();
	exit(0);
}

int main(int argc, char *argv[])
{
	int i = 0;
	char *backend = NULL;

	user = getpwuid(getuid());

	backend = getenv("LOG_BACKEND");

	/* For historical reasons we make MySQL the main backend */
	if (backend == NULL)
#ifdef HAVE_LIBMYSQLCLIENT
		backend = strdup("mysql");
#else
		backend = strdup("dummy");
#endif
	if (*backend == '\0')
#ifdef HAVE_LIBMYSQLCLIENT
		backend = strdup("mysql");
#else
		backend = strdup("dummy");
#endif

	/* Load the logging backend function pointers */
	if (symloader(backend))
		PoorExit(1);
	free(backend);

	/* Handle several signals to close the database correctly and disable CTRL+C */
	signal(SIGINT, SIG_IGN);
	signal(SIGHUP, to_end_sigterm);
	signal(SIGTERM, to_end_sigterm);
	signal(SIGQUIT, to_end_sigterm);

	/* Parse command configuration file */
	if(ParseCommandsFile(argv[1] != NULL ? argv[1] : DEFAULT_COMMANDS_CFG))
		PoorExit(1);

	/* If there's a database configuration file we read it in the plugin */
	if (ReadDBConfig(DEFAULT_CFG))
		PoorExit(1);

	/* Connect to the database to log in the plugin */
	if (ConnectDB())
		PoorExit(1);

	/* This is a support function for the plugin, so he can "create" a database for logging if it doesn't exists. The MySQL plugin has support to do this */
	if (InitializeTable())
		PoorExitWithDB(1);

	/* Register the login in the plugin */
	time(&now);
	fn = localtime(&now);
	if (RegisterAction(user->pw_name, fn, "Logged in", NULL))
		PoorExitWithDB(1);

	/* Yeay!!! The interface */
	while ((i = runMenu()) != -1) {

		/* Register the action */
		time(&now);
		fn = localtime(&now);
		if (RegisterAction(user->pw_name, fn,  MenuItems[i].desc, MenuItems[i].command))
			PoorExitWithDB(1);

		/* We don't need asynchronous commands running so let's go by the simple way */
		system(MenuItems[i].command);

		/* Let's hope blink works */
		fprintf(stdout, BOLD_BLINK "Press intro to continue..." RESET);
		fflush(stdout);
		getchar();
	}

	/* Shut the connection to the database down and register the logout */
	fprintf(stdout, "Closing connection with the database.");
	time(&now);
	fn = localtime(&now);
	if (RegisterAction(user->pw_name, fn, "Logged out", NULL)) {
		printf(RED " [FAIL]\n" RESET);
		PoorExitWithDB(1);
	}
	CloseDB();
	printf(GREEN " [DONE]\n" RESET);

	PoorExitWithDB(0);

	return 0;
}

/* EOF */
